/* GTK - The GIMP Toolkit
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 *
 * Author: Thura Hlaing <trhura@gmail.com>
 *
 */

#include <callbacks.h>
#include <gdk/gdkkeysyms.h>
#include <gtk/gtk.h>

static gboolean		handle_control_keys (GtkIMContextBurmese *context, GdkEventKey *event, gboolean *handled);
static gboolean		callback_get_burmese_string (GtkIMContextBurmese *context, GdkEventKey *event);
static gboolean		callback_get_english_string (GtkIMContextBurmese *context, GdkEventKey *event); 
static gboolean		g_unichar_is_burmese_medial (gunichar chr);
static gboolean		g_unichar_is_burmese_consonant (gunichar chr);

gboolean callback_handle_keypress (GtkIMContextBurmese *context, GdkEventKey *event)
{
	/* Free previous surrounding_text & get the new one*/
	g_free (context->surrounding_text);
	gtk_im_context_get_surrounding (GTK_IM_CONTEXT (context), &(context->surrounding_text), &(context->cur_pos));

	if (event->type != GDK_KEY_PRESS)
		return FALSE;

	if ((event->state == GDK_MOD1_MASK) &&  (event->keyval == GDK_KEY_Shift_L)) {
		context->language = !context->language;
	}
	
	if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) != 0)
		return FALSE;

	if (context->language == 0)
		return callback_get_english_string (context, event);
	else
		return callback_get_burmese_string (context, event);
}

static gboolean handle_control_keys (GtkIMContextBurmese *context, GdkEventKey *event, gboolean *handled)
{
		/* Ignore Key Release events */


	/* static gboolean shift_alone = FALSE; */
	/* static guint32	shift_ptime = 0;  */

	/* /\* Shift toggle language, check only shift key is pressed and is not presed for too long. *\/ */
	/* if (event->keyval == GDK_KEY_Shift_L) { */
	/* 	if (event->type == GDK_KEY_PRESS) { */
	/* 		shift_ptime = event->time; */
	/* 		shift_alone = TRUE; */
	/* 	} */
		
	/* 	if (event->type == GDK_KEY_RELEASE && shift_alone && (shift_ptime + 300) > event->time) { */
	/* 		context->language = ! context->language;  */
	/* 	} */
	/* 	*handled = TRUE; */
	/* 	return TRUE;  */
	/* } */


	/* Ugly workaround for selection, check is there any selected text. */
	/* gpointer root_window; */
	
	/* gdk_window_get_user_data (event->window, &root_window); */
	/* context->widget = (gpointer) gtk_window_get_focus (root_window); */
	/* g_assert (context->widget != NULL); */

	/* if (GTK_IS_EDITABLE (context->widget)) */
	/* 	context->has_selection = gtk_editable_get_selection_bounds (GTK_EDITABLE (context->widget), */
	/* 																NULL, NULL); */
	/* if (GTK_IS_TEXT_VIEW (context->widget))  */
	/* 	context->has_selection = gtk_text_buffer_get_selection_bounds (gtk_text_view_get_buffer (context->widget), */
	/* 																   NULL, NULL); */

	/* gchar *tmp1 = NULL, *tmp2 =NULL; */
	/* gunichar chr1, chr2; */
	/* gboolean first_run = TRUE; */
	/* gint i = 0; */
	
	/* if (event->keyval == GDK_KEY_BackSpace) { */
	/* 	if (context->has_selection) { */
	/* 		/\* If there is selected text, return to deafult handler *\/ */
	/* 		*handled = FALSE; */
	/* 		return TRUE; */
	/* 	} */
	/* 	if (event->state & GDK_CONTROL_MASK) { */
	/* 		/\* Ctrl + Backspace = Delete word backward *\/ */
	/* 		tmp1 = g_utf8_find_prev_char (context->surrounding_text, context->surrounding_text+context->cur_pos); */
	/* 		while (tmp1 != NULL) */
	/* 		{ */
	/* 			chr1 = g_utf8_get_char (tmp1); */
	/* 			tmp1 = g_utf8_find_prev_char (context->surrounding_text, tmp1); */
	/* 			if (first_run && (g_unichar_ispunct (chr1) || g_unichar_isspace (chr1))) { */
	/* 				i++; */
	/* 				continue; */
	/* 			} */
				
	/* 			if (g_unichar_ispunct (chr1) || g_unichar_isspace (chr1))  */
	/* 				break; */
				
	/* 			first_run = FALSE; */
	/* 			i++;  */
	/* 		} */
	/* 		gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -i, i); */
	/* 	} else { */
	/* 		tmp1 = g_utf8_find_prev_char (context->surrounding_text, context->surrounding_text+context->cur_pos); */
	/* 		if (tmp1 == NULL) { */
	/* 			return TRUE; */
	/* 		} */
			
	/* 		tmp2 = g_utf8_find_prev_char (context->surrounding_text, tmp1); */
	/* 		if (tmp2 == NULL) { */
	/* 			return TRUE; */
	/* 		} */

	/* 		chr1 = g_utf8_get_char (tmp1); */
	/* 		chr2 = g_utf8_get_char (tmp2); */
	/* 		if (chr1 == MYANMAR_VOWEL_SIGN_E) { */
	/* 			/\* if previous character is vowel e, delete medials & the consonant first */
	/* 			 * put ZWNJ infront vowel e before deleting the consonant. if ZWNJ is found before */
	/* 			 * vowel e, the vowel e is unattached, delete both ZWNJ & vowel e. */
	/* 			 *\/ */
	/* 			if (chr2 == ZERO_WIDTH_NON_JOINER) { */
	/* 				gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -2, 2); */
	/* 			} else if (g_unichar_is_burmese_medial (chr2)) { */
	/* 				gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -2, 1); */
	/* 			} else if (g_unichar_is_burmese_consonant(chr2)) { */
	/* 				gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -2, 2); */
	/* 				g_signal_emit_by_name (context, "commit", g_strdup_printf ("%lc%lc", ZERO_WIDTH_NON_JOINER, MYANMAR_VOWEL_SIGN_E));  */
	/* 			} */
	/* 		} else { */
	/* 			/\* Otherwise, delete previous character *\/ */
	/* 			gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -1, 1); */
	/* 		} */
	/* 	} */
	/* 	*handled = TRUE; */
	/* 	return TRUE;  */
	/* } */
		
	/* if (event->keyval == GDK_KEY_Delete) { */
	/* 	if (context->has_selection) { */
	/* 		/\* If there is selected text, return to deafult handler *\/ */
	/* 		*handled = FALSE; */
	/* 		return TRUE; */
	/* 	} */
	/* 	if (event->state & GDK_CONTROL_MASK) { */
	/* 		/\* Ctrl + Delete -> delete next word *\/ */
	/* 		tmp1 = context->surrounding_text+context->cur_pos; */
	/* 		while (tmp1 != NULL) */
	/* 		{ */
	/* 			chr1 = g_utf8_get_char (tmp1); */
	/* 			tmp1 = g_utf8_find_next_char (tmp1, NULL); */
	/* 			// g_printf ("current char = %lc, i=%d, %x\n", chr1, i, tmp1); */
	/* 			if (first_run && (g_unichar_ispunct (chr1) || g_unichar_isspace (chr1))) { */
	/* 				i++; */
	/* 				continue; */
	/* 			} */
				
	/* 			if (chr1 == '\0' || g_unichar_ispunct (chr1) || g_unichar_isspace (chr1))  */
	/* 				break; */
				
	/* 			first_run = FALSE; */
	/* 			i++;  */
	/* 		} */
	/* 		gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), 0, i); */
	/* 	} else { */
	/* 		/\* Otherwise, delete next cluster *\/ */
	/* 		tmp1 = context->surrounding_text+context->cur_pos; */
	/* 		while (tmp1 != NULL) */
	/* 		{ */
	/* 			chr1 = g_utf8_get_char (tmp1); */
	/* 			tmp1 = g_utf8_find_next_char (tmp1, NULL); */
	/* 			// g_printf ("current char = %lc, i=%d\n", chr1, i); */

	/* 			if (! g_unichar_ismark(chr1) && ! g_unichar_isalpha(chr1)) { */
	/* 				if (i == 0) */
	/* 					/\* First run *\/ */
	/* 					i++; */
	/* 				break; */
	/* 			} */

	/* 			if (g_unichar_ismark (chr1)) { */
	/* 				i++; */
	/* 				continue; */
	/* 			} */

	/* 			if (g_unichar_isalpha (chr1)) { */
	/* 				if (i > 0) */
	/* 					break; */
	/* 				i++; */
	/* 				continue; */
	/* 			} */
	/* 		} */
	/* 		gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), 0, i); */
	/* 	} */
	/* 	*handled = TRUE; */
	/* 	return TRUE; */
	/* } */
		
	/* if (event->state & GDK_CONTROL_MASK || event->state & GDK_MOD1_MASK) */
	/* 	/\* use default handler for control & alt masked keys *\/ */
	/* 	return TRUE; */

	
	//	shift_alone = FALSE;
	return FALSE;
}

static gboolean callback_get_english_string (GtkIMContextBurmese *context, GdkEventKey *event)
{
	switch (event->keyval) {
		
	case GDK_KEY_grave: 
		g_signal_emit_by_name (context, "commit", "`");
		break;

	case GDK_KEY_asciitilde:
		g_signal_emit_by_name (context, "commit", "~"); 
		break;
	
	case GDK_KEY_1:
		g_signal_emit_by_name (context, "commit", "1"); 
		break;
	
	case GDK_KEY_2:
		g_signal_emit_by_name (context, "commit", "2"); 
		break;

	case GDK_KEY_3:
		g_signal_emit_by_name (context, "commit", "3"); 
		break;

	case GDK_KEY_4:
		g_signal_emit_by_name (context, "commit", "4"); 
		break;

	case GDK_KEY_5:
		g_signal_emit_by_name (context, "commit", "5"); 
		break;
		
	case GDK_KEY_6:
		g_signal_emit_by_name (context, "commit", "6"); 
		break;

	case GDK_KEY_7:
		g_signal_emit_by_name (context, "commit", "7"); 
		break;

	case GDK_KEY_8:
		g_signal_emit_by_name (context, "commit", "8"); 
		break;

	case GDK_KEY_9:
		g_signal_emit_by_name (context, "commit", "9"); 
		break;

	case GDK_KEY_0:
		g_signal_emit_by_name (context, "commit", "0"); 
		break;

	case GDK_KEY_minus:
		g_signal_emit_by_name (context, "commit", "-"); 
		break;

	case GDK_KEY_equal:
		g_signal_emit_by_name (context, "commit", "="); 
		break;
		
	case GDK_KEY_exclam:
		g_signal_emit_by_name (context, "commit", "!"); 
		break;

	case GDK_KEY_at:
		g_signal_emit_by_name (context, "commit", "@"); 

	case GDK_KEY_numbersign:
		g_signal_emit_by_name (context, "commit", "#"); 
		break;

	case GDK_KEY_dollar:
		g_signal_emit_by_name (context, "commit", "$"); 

	case GDK_KEY_percent:
		g_signal_emit_by_name (context, "commit", "%"); 

	case GDK_KEY_asciicircum:
		g_signal_emit_by_name (context, "commit", "^"); 
		break;
		
	case GDK_KEY_ampersand:
		g_signal_emit_by_name (context, "commit", "&"); 
		break;

	case GDK_KEY_asterisk:
		g_signal_emit_by_name (context, "commit", "*"); 
		break;
		
	case GDK_KEY_parenleft:
		g_signal_emit_by_name (context, "commit", "("); 
		break;

	case GDK_KEY_parenright:
		g_signal_emit_by_name (context, "commit", ")"); 
		break;

	case GDK_KEY_underscore:
		g_signal_emit_by_name (context, "commit", "_"); 
		break;

	case GDK_KEY_plus:
		g_signal_emit_by_name (context, "commit", "+"); 
		break;

	case GDK_KEY_q:
		g_signal_emit_by_name (context, "commit", "q"); 
		break;
		
	case GDK_KEY_Q:
		g_signal_emit_by_name (context, "commit", "Q"); 
		break;

	case GDK_KEY_w:
		g_signal_emit_by_name (context, "commit", "w"); 
		break;

	case GDK_KEY_W:
		g_signal_emit_by_name (context, "commit", "W"); 
		break;

	case GDK_KEY_e:
		g_signal_emit_by_name (context, "commit", "e"); 
		break;
		
	case GDK_KEY_E:
		g_signal_emit_by_name (context, "commit", "E"); 
		break;
		
	case GDK_KEY_r:
		g_signal_emit_by_name (context, "commit", "r"); 
		break;
		
	case GDK_KEY_R:
		g_signal_emit_by_name (context, "commit", "R"); 
		
	case GDK_KEY_t:
		g_signal_emit_by_name (context, "commit", "t"); 
		break;
		
	case GDK_KEY_T:
		g_signal_emit_by_name (context, "commit", "T"); 
		break;
		
	case GDK_KEY_y:
		g_signal_emit_by_name (context, "commit", "y"); 
		break;
		
	case GDK_KEY_Y:
		g_signal_emit_by_name (context, "commit", "Y"); 
		break;
		
	case GDK_KEY_u:
		g_signal_emit_by_name (context, "commit", "u"); 
		break;
		
	case GDK_KEY_U:
		g_signal_emit_by_name (context, "commit", "U"); 
		break;
				
	case GDK_KEY_i:
		g_signal_emit_by_name (context, "commit", "i"); 
		break;
		
	case GDK_KEY_I:
		g_signal_emit_by_name (context, "commit", "I"); 
		break;
		
	case GDK_KEY_o:
		g_signal_emit_by_name (context, "commit", "o"); 
		break;
		
	case GDK_KEY_O:
		g_signal_emit_by_name (context, "commit", "O"); 
		break;
		
	case GDK_KEY_p:
		g_signal_emit_by_name (context, "commit", "p"); 
		break;
		
	case GDK_KEY_P:
		g_signal_emit_by_name (context, "commit", "P"); 
		break;
		
	case GDK_KEY_bracketleft:
		g_signal_emit_by_name (context, "commit", "["); 
		break;
		
	case GDK_KEY_bracketright:
		g_signal_emit_by_name (context, "commit", "]"); 
		break;

	case GDK_KEY_braceleft:
		g_signal_emit_by_name (context, "commit", "("); 
		break;
		
	case GDK_KEY_braceright:
		g_signal_emit_by_name (context, "commit", "}"); 
		break;
		
	case GDK_KEY_a: 
		g_signal_emit_by_name (context, "commit", "a"); 
		break;
		
	case GDK_KEY_A:
		g_signal_emit_by_name (context, "commit", "A"); 
		break;
		
	case GDK_KEY_s:
		g_signal_emit_by_name (context, "commit", "s"); 
		break;
		
	case GDK_KEY_S:
		g_signal_emit_by_name (context, "commit", "S"); 
		break;
		
	case GDK_KEY_d:
		g_signal_emit_by_name (context, "commit", "d"); 
		break;
		
	case GDK_KEY_D:
		g_signal_emit_by_name (context, "commit", "D"); 
		break;
		
	case GDK_KEY_f:
		g_signal_emit_by_name (context, "commit", "f"); 
		break;
		
	case GDK_KEY_F:
		g_signal_emit_by_name (context, "commit", "F"); 
		break;
		
	case GDK_KEY_g:
		g_signal_emit_by_name (context, "commit", "g"); 
		break;
		
	case GDK_KEY_G:
		g_signal_emit_by_name (context, "commit", "G"); 
		break;
		
	case GDK_KEY_h:
		g_signal_emit_by_name (context, "commit", "h"); 
		break;
		
	case GDK_KEY_H:
		g_signal_emit_by_name (context, "commit", "H"); 
		break;
		
	case GDK_KEY_j:
		g_signal_emit_by_name (context, "commit", "j"); 
		break;
		
	case GDK_KEY_J:
		g_signal_emit_by_name (context, "commit", "J"); 
		break;
		
	case GDK_KEY_k:
		g_signal_emit_by_name (context, "commit", "k"); 
		break;
		
	case GDK_KEY_K:
		g_signal_emit_by_name (context, "commit", "K"); 
		break;
		
	case GDK_KEY_l:
		g_signal_emit_by_name (context, "commit", "l"); 
		break;
		
	case GDK_KEY_L:
		g_signal_emit_by_name (context, "commit", "L"); 
		break;
		
	case GDK_KEY_semicolon:
		g_signal_emit_by_name (context, "commit", ";"); 
		break;
		
	case GDK_KEY_colon:
		g_signal_emit_by_name (context, "commit", ":"); 
		break;
				
	case GDK_KEY_apostrophe:
		g_signal_emit_by_name (context, "commit", "'"); 
		break;
		
	case GDK_KEY_quotedbl:
		g_signal_emit_by_name (context, "commit", "\""); 
		break;
		
	case GDK_KEY_backslash:
		g_signal_emit_by_name (context, "commit", "\\"); 
		break;
		
	case GDK_KEY_bar:
		g_signal_emit_by_name (context, "commit", "|"); 
		break;

	case GDK_KEY_z:
		g_signal_emit_by_name (context, "commit", "z"); 
		break;
		
	case GDK_KEY_Z:
		g_signal_emit_by_name (context, "commit", "Z"); 
		break;
		
	case GDK_KEY_x:
		g_signal_emit_by_name (context, "commit", "x"); 
		break;
		
	case GDK_KEY_X:
		g_signal_emit_by_name (context, "commit", "X"); 
		break;
		
	case GDK_KEY_c:
		g_signal_emit_by_name (context, "commit", "c"); 
		break;
		
	case GDK_KEY_C:
		g_signal_emit_by_name (context, "commit", "C"); 
		break;
		
	case GDK_KEY_v:
		g_signal_emit_by_name (context, "commit", "v"); 
		break;
		
	case GDK_KEY_V:
		g_signal_emit_by_name (context, "commit", "V"); 
		break;
		
	case GDK_KEY_b:
		g_signal_emit_by_name (context, "commit", "b"); 
		break;
		
	case GDK_KEY_B:
		g_signal_emit_by_name (context, "commit", "B"); 
		
	case GDK_KEY_n:
		g_signal_emit_by_name (context, "commit", "n"); 
		break;
		
	case GDK_KEY_N:
		g_signal_emit_by_name (context, "commit", "N"); 
		break;
		
	case GDK_KEY_m:
		g_signal_emit_by_name (context, "commit", "m"); 
		break;
		
	case GDK_KEY_M:
		g_signal_emit_by_name (context, "commit", "M"); 
		break;

	case GDK_KEY_less:
		g_signal_emit_by_name (context, "commit", "<");
		break;
		
	case GDK_KEY_greater:
		g_signal_emit_by_name (context, "commit", ">");
		break;
		
	case GDK_KEY_comma:
		g_signal_emit_by_name (context, "commit", ","); 
		break;
		
	case GDK_KEY_period:
		g_signal_emit_by_name (context, "commit", "."); 
		break;
		
	case GDK_KEY_slash:
		g_signal_emit_by_name (context, "commit", "/"); 
		break;
		
	case GDK_KEY_question:
		g_signal_emit_by_name (context, "commit", "?"); 
		break;
		
	case GDK_KEY_space:
		g_signal_emit_by_name (context, "commit", " ");
		break;

	default:
		return FALSE;
	}

	return TRUE;
}

static gboolean callback_get_burmese_string (GtkIMContextBurmese *context, GdkEventKey *event)
{
	/* string is normally 2 gunichar long, corresponding character & null */
	gunichar *string = g_malloc (sizeof (gunichar) * 2);
	gint size = 1;

	gunichar prev_char;
	gchar *tmp;

	switch (event->keyval) {

	case GDK_KEY_grave:
		context->third_level_on = TRUE;
		return FALSE;

	case GDK_KEY_asciitilde:
		string[0] = MYANMAR_LETTER_DDHA;
		break;
	
	case GDK_KEY_1:		
		string[0] = MYANMAR_DIGIT_ONE;
		break;
	
	case GDK_KEY_2:
		string[0] = MYANMAR_DIGIT_TWO;
		break;

	case GDK_KEY_3:
		string[0] = MYANMAR_DIGIT_THREE;
		break;

	case GDK_KEY_4:
		string[0] = MYANMAR_DIGIT_FOUR;
		break;

	case GDK_KEY_5:
		string[0] = MYANMAR_DIGIT_FIVE;
		break;
		
	case GDK_KEY_6:
		string[0] = MYANMAR_DIGIT_SIX;
		break;

	case GDK_KEY_7:
		string[0] = MYANMAR_DIGIT_SEVEN;
		break;

	case GDK_KEY_8:
		string[0] = MYANMAR_DIGIT_EIGHT;
		break;

	case GDK_KEY_9:
		string[0] = MYANMAR_DIGIT_NINE;
		break;

	case GDK_KEY_0:
		string[0] = MYANMAR_DIGIT_ZERO;
		break;

	case GDK_KEY_minus:
		string[0] = MINUS_SIGN;
		break;

	case GDK_KEY_equal:
		string[0] = EQUALS_SIGN;
		break;
		
	case GDK_KEY_exclam:
		string[0] = MYANMAR_LETTER_DDA;
		break;

	case GDK_KEY_at:
		string = g_realloc (string, 4 * sizeof (gunichar));
		string[0] = MYANMAR_LETTER_NNA;
		string[1] = MYANMAR_SIGN_VIRAMA;
		string[2] = context->third_level_on ? MYANMAR_LETTER_TTHA : MYANMAR_LETTER_DDA;
		size = 3;
		break;

	case GDK_KEY_numbersign:
		string[0] = MYANMAR_LETTER_TTA;
		break;

	case GDK_KEY_dollar:
		string = g_realloc (string, 5 * sizeof (gunichar));
		string[0] = MYANMAR_LETTER_KA;
		string[1] = MYANMAR_CONSONANT_SIGN_MEDIAL_YA;
		string[2] = MYANMAR_LETTER_PA;
		string[3] = MYANMAR_SIGN_ASAT;
		size = 4;
		break;

	case GDK_KEY_percent:
		string[0] = PERCENT_SIGN;
		break;

	case GDK_KEY_asciicircum:
		string[0] = SOLIDUS;
		break;
		
	case GDK_KEY_ampersand:
		string[0] = MYANMAR_LETTER_RA;
		break;

	case GDK_KEY_asterisk:
		string[0] = MYANMAR_LETTER_GA;
		break;
		
	case GDK_KEY_parenleft:
		string[0] = LEFT_PARENTHESIS;
		break;

	case GDK_KEY_parenright:
		string[0] = RIGHT_PARENTHESIS;
		break;

	case GDK_KEY_underscore:
		string[0] = SUMMATION;
		break;

	case GDK_KEY_plus:
		string[0] = PLUS_SIGN;
		break;

	case GDK_KEY_q:
		string[0] = MYANMAR_LETTER_CHA;
		break;
		
	case GDK_KEY_Q:
		string[0] = MYANMAR_LETTER_JHA;
		break;

	case GDK_KEY_w:
		string[0] = MYANMAR_LETTER_TA;
		break;

	case GDK_KEY_W:
		string[0] = MYANMAR_LETTER_WA;
		break;

	case GDK_KEY_e:
		string[0] = MYANMAR_LETTER_NA;
		break;
		
	case GDK_KEY_E:
		string[0] = MYANMAR_LETTER_I;
		break;
		
	case GDK_KEY_r:
		string[0] = MYANMAR_LETTER_MA;
		break;
		
	case GDK_KEY_R:
		string = g_realloc (string, 5 * sizeof (gunichar)); 
		string[0] = MYANMAR_SYMBOL_AFOREMENTIONED;
		string[1] = MYANMAR_LETTER_NGA;
		string[2] = MYANMAR_SIGN_ASAT;
		string[3] = MYANMAR_SIGN_VISARGA;
		size = 4;
		break;
		
	case GDK_KEY_t:
		string[0] = MYANMAR_LETTER_A;
		break;
		
	case GDK_KEY_T:
		string[0] = MYANMAR_LETTER_II;
		break;
		
	case GDK_KEY_y:
		string[0] = MYANMAR_LETTER_PA;
		break;
		
	case GDK_KEY_Y:
		string[0] = MYANMAR_SYMBOL_LOCATIVE;
		break;
		
	case GDK_KEY_u:
		string[0] = MYANMAR_LETTER_KA;
		break;
		
	case GDK_KEY_U:
		string[0] = MYANMAR_LETTER_U;
		break;
				
	case GDK_KEY_i:
		string[0] = MYANMAR_LETTER_NGA;
		break;
		
	case GDK_KEY_I:
		string[0] = MYANMAR_SYMBOL_COMPLETED;
		break;
		
	case GDK_KEY_o:
		string[0] = MYANMAR_LETTER_SA;
		break;
		
	case GDK_KEY_O:
		string[0] = MYANMAR_LETTER_GREAT_SA;
		break;
		
	case GDK_KEY_p:
		string[0] = MYANMAR_LETTER_CA;
		break;
		
	case GDK_KEY_P:
		string[0] = MYANMAR_LETTER_NNA;
		break;
		
	case GDK_KEY_bracketleft:
		string[0] = MYANMAR_LETTER_HA;
		break;
		
	case GDK_KEY_bracketright:
		string[0] = MYANMAR_LETTER_O;
		break;

	case GDK_KEY_braceleft:
		string[0] = MYANMAR_LETTER_E;
		break;
		
	case GDK_KEY_braceright:
		string[0] = MYANMAR_LETTER_AU;
		break;
		
	case GDK_KEY_a: 
		string = g_realloc (string, 3 * sizeof (gunichar));
		string[0] = ZERO_WIDTH_NON_JOINER;
		string[1] = MYANMAR_VOWEL_SIGN_E;
		size = 2; 
		break;
		
	case GDK_KEY_A:
		string[0] = MYANMAR_LETTER_BA;
		break;
		
	case GDK_KEY_s:
		string[0] = MYANMAR_CONSONANT_SIGN_MEDIAL_YA;
		break;
		
	case GDK_KEY_S:
		string[0] = MYANMAR_CONSONANT_SIGN_MEDIAL_HA;
		break;
		
	case GDK_KEY_d:
		string[0] = MYANMAR_VOWEL_SIGN_I;
		break;
		
	case GDK_KEY_D:
		string[0] = MYANMAR_VOWEL_SIGN_II;
		break;
		
	case GDK_KEY_f:
		string[0] = MYANMAR_SIGN_ASAT;
		break;
		
	case GDK_KEY_F:
		string[0] = MYANMAR_SIGN_VIRAMA;
		break;
		
	case GDK_KEY_g:
		string[0] = MYANMAR_VOWEL_SIGN_TALL_AA;
		break;
		
	case GDK_KEY_G:
		string[0] = MYANMAR_CONSONANT_SIGN_MEDIAL_WA;
		break;
		
	case GDK_KEY_h:
		string[0] = MYANMAR_SIGN_DOT_BELOW;
		break;
		
	case GDK_KEY_H:
		string[0] = MYANMAR_SIGN_ANUSVARA;
		break;
		
	case GDK_KEY_j:
		string[0] = MYANMAR_CONSONANT_SIGN_MEDIAL_RA;
		break;
		
	case GDK_KEY_J:
		string[0] = MYANMAR_VOWEL_SIGN_AI;
		break;
		
	case GDK_KEY_k:
		string[0] = MYANMAR_VOWEL_SIGN_U;
		break;
		
	case GDK_KEY_K:
		string[0] = MYANMAR_LETTER_DA;
		break;
		
	case GDK_KEY_l:
		string[0] = MYANMAR_VOWEL_SIGN_UU;
		break;
		
	case GDK_KEY_L:
		string[0] = MYANMAR_LETTER_DHA;
		break;
		
	case GDK_KEY_semicolon:
		string[0] = MYANMAR_SIGN_VISARGA;
		break;
		
	case GDK_KEY_colon:
		string[0] = COLON;
		break;
				
	case GDK_KEY_apostrophe:
		/* Check which one to put, opening or close single quote */
		tmp = g_utf8_find_prev_char (context->surrounding_text, context->surrounding_text+context->cur_pos);
		while (TRUE)
		{
			if (tmp == NULL) {
				string[0] = LEFT_SINGLE_QUOTE;
				break;
			}

			prev_char = g_utf8_get_char (tmp);
			if (prev_char == RIGHT_SINGLE_QUOTE) {
				string[0] = LEFT_SINGLE_QUOTE;
				break;
			}
			if (prev_char == LEFT_SINGLE_QUOTE) {
				string[0] = RIGHT_SINGLE_QUOTE;
				break;
			}
			tmp = g_utf8_find_prev_char (context->surrounding_text, tmp);
		}
		break;
		
	case GDK_KEY_quotedbl:
		/* Check which one to put, opening or close double quote */
		tmp = g_utf8_find_prev_char (context->surrounding_text, context->surrounding_text+context->cur_pos);
		while (TRUE)
		{
			if (tmp == NULL) {
				string[0] = LEFT_DOUBLE_QUOTE;
				break;
			}

			prev_char = g_utf8_get_char (tmp);
			if (prev_char == RIGHT_DOUBLE_QUOTE) {
				string[0] = LEFT_DOUBLE_QUOTE;
				break;
			}
			if (prev_char == LEFT_DOUBLE_QUOTE) {
				string[0] = RIGHT_DOUBLE_QUOTE;
				break;
			}
			tmp = g_utf8_find_prev_char (context->surrounding_text, tmp);
		}
		break;
		
	case GDK_KEY_backslash:
		string[0] = MYANMAR_SYMBOL_GENITIVE;
		break;
		
	case GDK_KEY_bar:
		string[0] = MYANMAR_LETTER_NYA;
		break;

	case GDK_KEY_z:
		string[0] = MYANMAR_LETTER_PHA;
		break;
		
	case GDK_KEY_Z:
		string[0] = MYANMAR_LETTER_JA;
		break;
		
	case GDK_KEY_x:
		string[0] = MYANMAR_LETTER_THA;
		break;
		
	case GDK_KEY_X:
		string[0] = MYANMAR_LETTER_TTHA;
		break;
		
	case GDK_KEY_c:
		string[0] = MYANMAR_LETTER_KHA;
		break;
		
	case GDK_KEY_C:
		string[0] = MYANMAR_LETTER_GHA;
		break;
		
	case GDK_KEY_v:
		string[0] = MYANMAR_LETTER_LA;
		break;
		
	case GDK_KEY_V:
		string[0] = MYANMAR_LETTER_LLA;
		break;
		
	case GDK_KEY_b:
		string[0] = MYANMAR_LETTER_BHA;
		break;
		
		// case GDK_KEY_B:
		// string[0] = MYANMAR_LETTER_GREAT_SA;
		// break;
		
	case GDK_KEY_n:
		string[0] = MYANMAR_LETTER_NYA;
		break;
		
	case GDK_KEY_N:
		string[0] = MYANMAR_LETTER_NNYA;
		break;
		
	case GDK_KEY_m:
		string[0] = MYANMAR_VOWEL_SIGN_AA;
		break;
		
	case GDK_KEY_M:
		string[0] = MYANMAR_LETTER_UU;
		break;
		
	case GDK_KEY_comma:
		string[0] = MYANMAR_LETTER_YA;
		break;
		
	case GDK_KEY_period:
		string[0] = FULL_STOP;
		break;
		
	case GDK_KEY_slash: 
		string[0] = MYANMAR_SIGN_SECTION;
		break;
		
	case GDK_KEY_question:
		string[0] = MYANMAR_SIGN_LITTLE_SECTION;
		break;

	case GDK_KEY_space:
		g_signal_emit_by_name (context, "commit", " ");
		break;

	default:
		g_free (string);
		return FALSE;
	}
	
	tmp = g_utf8_find_prev_char (context->surrounding_text, context->surrounding_text+context->cur_pos);
	if (tmp != NULL) {
		prev_char = g_utf8_get_char (tmp);
		
		if (prev_char == MYANMAR_VOWEL_SIGN_E) {
			/* if previous char is VOWLE E, switch place with current consonant or medial */
			tmp = g_utf8_find_prev_char (context->surrounding_text, tmp);
			
			if (tmp != NULL && g_utf8_get_char (tmp) == ZERO_WIDTH_NON_JOINER &&
				 size == 1 && g_unichar_is_burmese_consonant(string[0])) {
				/* If there is ZWNJ infront of vowel e, it is unattached, so
				 * delete ZWNJ, put vowel e behind consonant */
				gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -2, 2);
				string = g_realloc (string, 3 * sizeof (gunichar));
				string[1] = MYANMAR_VOWEL_SIGN_E;
				size = 2;
			} else if (g_unichar_is_burmese_medial(string[0]) && size == 1) {
				/* For medials, if there is vowel e infront, swap place */
				gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -1, 1);
				string = g_realloc (string, 3 * sizeof (gunichar));
				string[1] = MYANMAR_VOWEL_SIGN_E;
				size = 2;
			}
		}

		if (prev_char == MYANMAR_SIGN_ASAT && size == 1 && string[0] == MYANMAR_SIGN_DOT_BELOW) {
			/* Swap if ASAT is infront of DOT BELOW */
			gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (context), -1, 1);
			string = g_realloc (string, 3 * sizeof (gunichar));
			string[1] = MYANMAR_SIGN_ASAT;
			size = 2;
		}
	}
	
	context->third_level_on = FALSE;
	string[size] = '\0'; 

	gchar* utf8_string = g_ucs4_to_utf8 (string, -1, NULL, NULL, NULL);
	g_signal_emit_by_name (context, "commit", utf8_string);
	g_free (string);

	return TRUE;
} 

static gboolean g_unichar_is_burmese_consonant (gunichar chr)
{
	return (chr >= MYANMAR_LETTER_KA && chr <= MYANMAR_LETTER_A);
}

static gboolean g_unichar_is_burmese_medial (gunichar chr)
{
	return (chr >= MYANMAR_CONSONANT_SIGN_MEDIAL_YA && chr <= MYANMAR_CONSONANT_SIGN_MEDIAL_HA);
}
